package com.dx.pf.commons.utils;

import java.io.File;  
import java.io.IOException;  
import java.util.ArrayList;  
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.DirectoryWalker;
/**
* @ClassName: DeleteSVNTempFile 
* @Description: 删除SVN文件信息 
* @author wuzhenfang(wzfbj2008@163.com)
* @date 2016年4月5日 上午10:17:50 
* @version V1.0
 */
public class DeleteSVNTempFile {

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		FileCleaner cleaner = new FileCleaner();
		// File startDirectory = new
		// File("D:\\workspace\\branches\\pamirsshop_branches_8-30");
		// F:\motorlink
		File startDirectory = new File("E:\\SVNBio\\hm.customer\\branches\\customer-android-2.0.1");
		List<File> list = cleaner.clean(startDirectory);
		for (File file : list) {
			 System.out.println("file:"+file.getAbsolutePath());
		}
		System.out.println("共处理" + list.size() + "个文件");

	}
}

   
@SuppressWarnings("rawtypes")
class FileCleaner extends DirectoryWalker {

	public static String   SVN_TRUNK = "trunk";
	public static String   SVN_BRANCHES = "branches";
	public static String   SVN_TAGS = "tags";

	public static String   EMPTY_STRING = "";
	public static String[] EMPTY_STRING_ARRAY = new String[0];

	public final static String REGEX_OF_DIFF_INDEX = "===================================================================";

	/** WORD_SEPARATOR ( char )2 */
	public static final String WORD_SEPARATOR = Character.toString((char) 2);

	public FileCleaner() {
		super();
	}

	public List<File> clean(File startDirectory) throws IOException {
		List<File> results = new ArrayList<File>();
		walk(startDirectory, results);
		return results;
	}

	@Override
	protected void handleStart(File startDirectory, Collection results) throws IOException {
		System.out.println("-------开始清除-------");
	}

	@Override
	protected void handleEnd(Collection results) throws IOException {
		System.out.println("-------结束清除-------");
	}

	@Override
	protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) throws IOException {
		System.out.println("-------清除异常-------");
		super.handleCancelled(startDirectory, results, cancel);
	}

	@Override
	protected boolean handleIsCancelled(File file, int depth, Collection results) throws IOException {
		// 这里可以设置断点，比如当你找到某个类的时候，停止遍历,默认继续
		return false;
	}

	@Override
	protected void handleDirectoryStart(File directory, int depth, Collection results) throws IOException {
		// System.out.println("****开始处理:"+directory.getName()+"deep:"+depth+"results:"+results.toString());
	}

	@Override
	protected void handleDirectoryEnd(File directory, int depth, Collection results) throws IOException {
		// System.out.println("****结束处理:"+directory.getName()+"deep:"+depth+"results:"+results.toString());
	}

	@Override
	protected void handleRestricted(File directory, int depth, Collection results) throws IOException {
		System.out.println("****受限制目录:" + directory.getName() + "deep:" + depth + "results:" + results.toString());
	}

	/**
	 * 是否处理某个目录.返回false 不处理
	 * @see 这里直接删除.svn.然后不处理.
	 */
	@Override
	protected boolean handleDirectory(File directory, int depth, Collection results) {
		// delete svn directories and then skip
		if (".svn".equals(directory.getName())) {
			deleteDirectory(directory, results);
			return false;
		} else {
			results.add(directory);// 删除.svn,还有哪些文件夹
			return true;
		}

	}

	/**
	 * 删除文件，并把文件加到删除列表中
	 */
	@Override
	protected void handleFile(File file, int depth, Collection results) {
		// delete file and add to list of deleted
		// file.delete();
		// results.add(file);
		// 删除.svn文件后，还有哪些文件
	}

	/**
	 * 删除目录及目录下的文件夹和文件
	 * @param directory
	 * @param results
	 */
	private void deleteDirectory(File directory, Collection results) {
		if (directory.isDirectory()) {
			File[] list = directory.listFiles();
			for (File file : list) {
				deleteDirectory(file, results);
			}
		}
		Log(directory.delete(), directory);
		results.add(directory);// 删除文件
	}

	/**
	 * 删除文件或者目录失败日志
	 * @param flag
	 */
	private void Log(boolean flag, File directory) {
		if (!flag) {
			System.err.println("删除文件失败:" + directory.getAbsolutePath());
		} else {
			System.out.println("delete:" + directory.getAbsolutePath());
		}
	}

	// -----------------------SVNUtil--------------------------------------

	private static Pattern unifiedDiffChunkRe = Pattern.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@$");

	/**
	 * parse the path of file in project from it's svn path.
	 * 
	 * @return e.g. reviewboardtest/pagecache-webx3-ga-example/pagecache-webx3-ga -example-web/src/main/webapp/WEB-INF/sadfsadfsqlmapadsaf.xml
	 * @throws Exception
	 */
	public static String parseFileProjectPathFromSvnPath(String svnPath) throws Exception {
		if (StringUtil.isBlank(svnPath)) {
			return EMPTY_STRING;
		}

		int index = -1;

		int indexOfTrunk = svnPath.indexOf(SVN_TRUNK);
		int indexOfBranches = svnPath.indexOf(SVN_BRANCHES);

		// 必须找到第一个trunk或branches, 文件路径自有的关键字不能算.
		if (-1 == indexOfTrunk && -1 != indexOfBranches) {
			index = indexOfBranches + SVN_BRANCHES.length() + 1;
		} else if (-1 == indexOfBranches && -1 != indexOfTrunk) {
			index = indexOfTrunk + SVN_TRUNK.length() + 1;
		} else if (-1 == indexOfBranches && -1 == indexOfTrunk) {
			throw new Exception(svnPath + " is a illegal svn path");
		} else if (-1 != indexOfBranches && -1 != indexOfTrunk) {
			if (indexOfBranches < indexOfTrunk) {
				index = indexOfBranches + SVN_BRANCHES.length() + 1;
			} else if (indexOfBranches > indexOfTrunk) {
				index = indexOfTrunk + SVN_TRUNK.length() + 1;
			}
		}
		return svnPath.substring(index);
	}

	/**
	 * parse the path of file in project from it's svn path with svn prefix
	 * @return e.g. trunk/reviewboardtest/pagecache-webx3-ga-example/pagecache-webx3 -ga-example-web/src/main/webapp/WEB-INF/asdfsqlmapadsaf.xml
	 * @throws Exception
	 */
	public static String parseFileProjectPathFromSvnPathWithSvnPrefix(String svnPath) throws Exception {
		if (StringUtil.isBlank(svnPath)) {
			return EMPTY_STRING;
		}

		int index = -1;

		int indexOfTrunk = svnPath.indexOf(SVN_TRUNK);
		int indexOfBranches = svnPath.indexOf(SVN_BRANCHES);

		// 必须找到第一个trunk或branches, 文件路径自有的关键字不能算.
		if (-1 == indexOfTrunk && -1 != indexOfBranches) {
			index = indexOfBranches;
		} else if (-1 == indexOfBranches && -1 != indexOfTrunk) {
			index = indexOfTrunk;
		} else if (-1 == indexOfBranches && -1 == indexOfTrunk) {
			throw new Exception(svnPath + " is a illegal svn path");
		} else if (-1 != indexOfBranches && -1 != indexOfTrunk) {
			if (indexOfBranches < indexOfTrunk) {
				index = indexOfBranches;
			} else if (indexOfBranches > indexOfTrunk) {
				index = indexOfTrunk;
			}
		}
		return svnPath.substring(index);
	}

	/**
	 * 将一个diff文本按照不同文件进行拆解
	 * @param diffContentAll 待拆解的内容
	 * @param pathList 完整文件名
	 * @return Map<String,String> <文件名, diff内容>
	 * @throws Exception
	 */
	public static Map<String, String> splitDiff(String diffContentAll, List<String> pathList) throws Exception {
		if (diffContentAll == null || diffContentAll.isEmpty() || pathList == null || pathList.isEmpty()) {
			return null;
		}
		Map<String, String> targetMap = new LinkedHashMap<String, String>();
		if (pathList.size() == 1) {
			targetMap.put(pathList.get(0), diffContentAll);
			return targetMap;
		}

		// 将所有文件分隔行分隔成一个易于区分的分隔符
		String tempString = diffContentAll.replaceAll(REGEX_OF_DIFF_INDEX, WORD_SEPARATOR);

		String[] diffSplit = tempString.split(WORD_SEPARATOR);

		// i = 1 是因为第一个是多余的且空.
		for (int i = 1; i < diffSplit.length; i++) {

			String diffContent = EMPTY_STRING;
			String key = EMPTY_STRING;
			try {
				diffContent = diffSplit[i];
			} catch (Exception e) {
				throw new Exception("数组越界: 从diffSplit获取数据, length=" + diffSplit.length + " 但是i= " + i);
			}
			try {
				key = pathList.get(i - 1);
			} catch (Exception e) {
				throw new Exception("List越界: 从pathList获取数据, size=" + pathList.size() + " 但是i= " + (i - 1));
			}

			targetMap.put(key, diffContent);
		}

		return targetMap;
	}

	/**
	 * 拼装DIFF内容到新文件
	 * @param originalFileName 原文件的完整文件名
	 * @param diffFileName Diff文件的完整文件名
	 * @return String 拼装后的完整内容
	 */
	public static String patchDiffFile(String originalFileName, String diffFileName) throws Exception {

		List<String> original = FileUtil.fileToListByLine(originalFileName);
		List<String> patched = FileUtil.fileToListByLine(diffFileName);

		return patchDiff(original, patched);
	}

	/**
	 * 拼装DIFF内容到新文件
	 * @param originalFileContent 原文件的内容
	 * @param diffFileContent Diff文件的内容
	 * @return String 拼装后的完整内容
	 */
	public static String patchDiffContent(String originalFileContent, String diffFileContent) throws Exception {

		List<String> original = FileUtil.stringToListByLine(originalFileContent);
		List<String> patched = FileUtil.stringToListByLine(diffFileContent);

		return patchDiff(original, patched);
	}

	/**
	 * 拼装DIFF内容到新文件
	 * @param originalFileLineList 原文件按行的内容集合
	 * @param diffFileLineList Diff文件按行的内容集合
	 * @return String 拼装后的完整内容
	 */
	private static String patchDiff(List<String> originalFileLineList, List<String> diffFileLineList) {

		Map<Integer, String> mapInsert = new LinkedHashMap<Integer, String>();
		Map<Integer, String> mapDelete = new LinkedHashMap<Integer, String>();

		int index = 0;
		boolean flag = false;

		for (String line : diffFileLineList) {

			Matcher matcherOfRevision = unifiedDiffChunkRe.matcher(line);

			/** 解析出初始行号 */
			if (matcherOfRevision.find()) {
				String str = matcherOfRevision.group();
				str = str.replaceAll("@@", "").trim().split(",")[0].replace("-", "");
				index = Integer.parseInt(str);
				flag = true;
				continue;
			}

			if (flag) {
				// 如果是要从原来文件中删除的
				if (line.startsWith("-")) {
					continue;
				} else if (line.startsWith("+")) {
					mapInsert.put(index, line);
					index++;
				} else {
					index++;
				}
			}
		}

		index = 0;
		flag = false;
		for (String line : diffFileLineList) {

			Matcher matcherOfRevision = unifiedDiffChunkRe.matcher(line);

			/** 解析出初始行号 */
			if (matcherOfRevision.find()) {
				String str = matcherOfRevision.group();
				str = str.replaceAll("@@", "").trim().split(",")[0].replace("-", "");
				index = Integer.parseInt(str);
				flag = true;
				continue;
			}

			if (flag) {
				// 如果是要从原来文件中删除的
				if (line.startsWith("+")) {
					continue;
				} else if (line.startsWith("-")) {
					mapDelete.put(index, line);
					index++;
				} else {
					index++;
				}
			}
		}

		// 现在已经获得了两个可以用的ADD和DELETE的map了.
		List<String> tempFile = new ArrayList<String>();
		List<String> newFile = new ArrayList<String>();
		int lineIndex = 0;

		// 先处理mapDelete
		for (String line : originalFileLineList) {
			lineIndex++;
			String lineContentDelete = mapDelete.get(lineIndex);

			if (null == lineContentDelete) {
				// 此行没有变动
				tempFile.add(line);
			}
		}

		// 现在处理mapInsert
		lineIndex = 0;
		for (String line : tempFile) {
			lineIndex++;
			String lineContentInsert = mapInsert.get(lineIndex);

			if (null == lineContentInsert) {
				newFile.add(line);
			} else {
				boolean isOk = true;
				while (isOk) {
					newFile.add(lineContentInsert.replaceFirst("\\+", ""));
					mapInsert.put(lineIndex, null);
					lineIndex++;
					lineContentInsert = mapInsert.get(lineIndex);

					if (null == lineContentInsert)
						isOk = false;
				}
				newFile.add(line);
			}
		}

		// 接下去要把mapInsert中多余的加入newFile中去.
		for (int _index : mapInsert.keySet()) {
			String lineContent = mapInsert.get(_index);
			if (null == lineContent)
				continue;

			newFile.add(lineContent.replaceFirst("\\+", ""));
		}

		StringBuilder newContent = new StringBuilder();
		if ("\n".equalsIgnoreCase(newFile.get(newFile.size() - 1))) {
			newFile.remove(newFile.size() - 1);
		}

		for (String newLine : newFile) {
			newContent.append(newLine).append("\n");
		}

		return newContent.toString();
	}
}  